import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.io.IOException;
import java.net.Socket;
import java.net.ServerSocket;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.LinkedBlockingQueue;

public class GameServer {

	private static Socket clientSocket = null;
	private static ServerSocket serverSocket = null;

	private static final int maxClientsCount = 2;
	private static final clientThread[] threads = new clientThread[maxClientsCount];

	public static LinkedBlockingDeque<int[][]> messages;

	public static void main(String args[]) {

		int portNumber = 2222;
		int[][] game_matrix_server_table;
		game_matrix_server_table = new int[20][20];
		game_matrix_server_table[10][10] = 5;
		GameServer.messages = new LinkedBlockingDeque<int[][]>();

		try {
			serverSocket = new ServerSocket(portNumber);
		} catch (IOException e) {
			System.out.println(e);
		}

		while (true) {
			try {
				clientSocket = serverSocket.accept();
				int i = 0;
				for (i = 0; i < maxClientsCount; i++) {
					if (threads[i] == null) {
						(threads[i] = new clientThread(clientSocket, threads))
								.start();
						break;
					}
				}

				if (i == maxClientsCount) {
					clientSocket.close();
				}
			} catch (IOException e) {
				System.out.println(e);
			}
		}
	}
}

class clientThread extends Thread {

	private ObjectInputStream object_input_stream = null;
	private ObjectOutputStream object_output_stream = null;

	private Socket clientSocket = null;

	private final clientThread[] threads;

	private int maxClientsCount;
	private int state_counter = 0;

	public boolean game_player_ready = false;
	private boolean player_one_ready = false;
	private boolean player_two_ready = false;

	public clientThread(Socket clientSocket, clientThread[] threads) {
		this.threads = threads;
		this.clientSocket = clientSocket;
		maxClientsCount = threads.length;
	}

	public void run() {
		clientThread[] threads = this.threads;

		try {
			boolean who_starts;

			this.object_output_stream = new ObjectOutputStream(
					clientSocket.getOutputStream());
			this.object_input_stream = new ObjectInputStream(
					clientSocket.getInputStream());

			if (threads[1] == null) {
				who_starts = true;
			} else {
				who_starts = false;
			}
			if (this == threads[0]) {
				threads[0].object_output_stream.writeObject(who_starts);
				threads[0].object_output_stream.flush();
			}
			if (this == threads[1]) {
				threads[1].object_output_stream.writeObject(who_starts);
				threads[1].object_output_stream.flush();
			}

			while (true) {
				switch (this.state_counter) {
				case 0:
					this.game_player_ready = (boolean) this.object_input_stream
							.readObject();
					if (this == threads[0]) {
						this.player_one_ready = true;
						this.state_counter++;
						System.out.println("Player ONE Ready!");
					}
					if (this == threads[1]) {
						this.player_two_ready = true;
						this.state_counter++;
						System.out.println("Player TWO Ready!");
					}
					break;
				case 1:
					try {
						String opponent_name_server;
						opponent_name_server = (String) this.object_input_stream
								.readObject();
						if (this == threads[0]) {
							threads[1].object_output_stream
									.writeObject(opponent_name_server);
							threads[1].object_output_stream.flush();
						}
						if (this == threads[1]) {
							threads[0].object_output_stream
									.writeObject(opponent_name_server);
							threads[0].object_output_stream.flush();
						}
					} catch (IOException e) {
						System.out.println(e);
					}
					this.state_counter++;
					break;
				case 2:
					try {
						GameServer.messages
								.addFirst((int[][]) this.object_input_stream
										.readObject());
						System.out.println("Object Received SERVER");
					} catch (IOException e) {
						System.out.println(e);
					}
					this.state_counter++;
					break;
				case 3:
					int[][] table;
					table = GameServer.messages.getFirst();

					if (this == threads[0]) {
						System.out.println("Sending GameMatrix To Player TWO!");
						threads[1].object_output_stream.writeObject(table);
						threads[1].object_output_stream.flush();
					}
					if (this == threads[1]) {
						System.out.println("Sending GameMatrix To Player ONE!");
						threads[0].object_output_stream.writeObject(table);
						threads[0].object_output_stream.flush();
					}
					table = null;
					this.state_counter--;
					break;
				}
			}
		} catch (IOException e) {
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		}
	}
}
